package cn.imatu.framework.data.mate.fieldconvert;

import cn.imatu.framework.data.mate.fieldconvert.model.AnnotInfo;
import cn.imatu.framework.data.mate.fieldconvert.model.FieldDefine;
import cn.imatu.framework.tool.core.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 基本类型字段值处理器
 * @param <T> 字段类型
 * @author shenguangyang
 */
@SuppressWarnings("all")
public interface ConvertFieldTypeHandler<T> {
    /**
     * 设置字段值<br>
     * 每个对象的属性都会调用一次, 比如需要处理一个对象, 其中有10个字段需要进行字段绑定操作, 那么就会被调用10次
     *
     * @param metaObject     处理的对象元数据
     * @param fieldDefine 字段定义数据, 可以获取当前处理的字段上自定义的字段绑定注解数据
     */
    void setValue(Collection<String> valueList, MetaObject metaObject, Field targetField, AnnotInfo annot);

    /**
     * 对传入的字段值进行转换
     */
    List<String> getValue(Object value, FieldDefine fieldDefine);


    @Component
    class StringType implements ConvertFieldTypeHandler<String> {

        @Override
        public void setValue(Collection<String> valueList, MetaObject metaObject, Field targetField, AnnotInfo annot) {
            String targetValue = valueList.stream().map(String::valueOf).collect(Collectors.joining(annot.getDelimiter()));
            metaObject.setValue(targetField.getName(), targetValue);
        }

        @Override
        public List<String> getValue(Object value, FieldDefine fieldDefine) {
            if (value == null) {
                return new ArrayList<>();
            }
            return Arrays.stream(value.toString().split(fieldDefine.getAnnot().getDelimiter())).collect(Collectors.toList());
        }
    }

    @Component
    class StringArray implements ConvertFieldTypeHandler<String[]> {

        @Override
        public void setValue(Collection<String> valueList, MetaObject metaObject, Field targetField, AnnotInfo annot) {
            String[] targetValue = valueList.stream().map(String::valueOf).toArray(String[]::new);
            metaObject.setValue(targetField.getName(), targetValue);
        }

        @Override
        public List<String> getValue(Object value, FieldDefine fieldDefine) {
            if (value == null) {
                return new ArrayList<>();
            }
            String[] targetValue = (String[]) value;
            return Arrays.stream(targetValue).collect(Collectors.toList());
        }
    }

    @Component
    class StringList implements ConvertFieldTypeHandler<List<String>> {

        @Override
        public void setValue(Collection<String> valueList, MetaObject metaObject, Field targetField, AnnotInfo annot) {
            Object targetValue = valueList.stream().map(String::valueOf).collect(Collectors.toList());
            metaObject.setValue(targetField.getName(), targetValue);
        }

        @Override
        public List<String> getValue(Object value, FieldDefine fieldDefine) {
            return (List<String>) value;
        }
    }

    @Component
    class StringSet implements ConvertFieldTypeHandler<Set<String>> {

        @Override
        public void setValue(Collection<String> valueList, MetaObject metaObject, Field targetField, AnnotInfo annot) {
            Object targetValue = valueList.stream().map(String::valueOf).collect(Collectors.toSet());
            metaObject.setValue(targetField.getName(), targetValue);
        }

        @Override
        public List<String> getValue(Object value, FieldDefine fieldDefine) {
            if (value == null) {
                return new ArrayList<>();
            }
            return new ArrayList<>((Set<String>) value);
        }
    }

}
